import argparse
import codecs
import platform
import subprocess
import shutil
from functools import partial
from collections import defaultdict
import os
import sys
import glob
import math
import cv2
import math
import pandas as pd
from PIL import Image, ImageQt
import numpy as np
from PyQt5 import QtCore
from PyQt5.QtMultimedia import QMediaContent, QMediaPlayer
from PyQt5.QtMultimediaWidgets import QVideoWidget
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from libs.utils import *
from wenxinMV import MV
from libs.ustr import ustr
from libs.genImage import GenerateDialog
from libs.exportDia import ExportDialog


class Storage():
    def __init__(self) -> None:
        self.storageDict = {'index':[], 'lrc':[], 'path':[], 'time':[]}
        self.maxIndex = -1

    def reset(self):
        self.storageDict = {'index':[], 'lrc':[], 'path':[], 'time':[]}
        self.maxIndex = -1

    def append(self, i, l, p, t):
        self.storageDict['index'].append(i)
        self.storageDict['lrc'].append(l)
        self.storageDict['path'].append(p)
        self.storageDict['time'].append(t.toString(Qt.ISODateWithMs))
        if i > self.maxIndex:
            self.maxIndex = i

    def insert(self, index, i, l, p, t):
        self.storageDict['index'].insert(index, i)
        self.storageDict['lrc'].insert(index, l)
        self.storageDict['path'].insert(index, p)
        self.storageDict['time'].insert(index, t.toString(Qt.ISODateWithMs))
        if i > self.maxIndex:
            self.maxIndex = i

    def delete(self, index):
        del self.storageDict['index'][index]
        del self.storageDict['lrc'][index]
        del self.storageDict['path'][index]
        del self.storageDict['time'][index]

    def modifyTimeByIndex(self, index, time):
        timeString = time.toString(Qt.ISODateWithMs)
        self.storageDict['time'][index] = timeString

    def modifyPathByIndex(self, index, path):
        self.storageDict['path'][index] = path

    def modifyLrcByIndex(self, index, lrc):
        self.storageDict['lrc'][index] = lrc

    def swapTwoByIndex(self, index1, index2):
        tindex = self.storageDict['index'][index1]
        tlrc = self.storageDict['lrc'][index1] 
        tpath = self.storageDict['path'][index1]
        ttime = self.storageDict['time'][index1]
        self.storageDict['index'][index1] = self.storageDict['index'][index2]
        self.storageDict['lrc'][index1] = self.storageDict['lrc'][index2]
        self.storageDict['path'][index1] = self.storageDict['path'][index2]
        self.storageDict['time'][index1] = self.storageDict['time'][index2]
        self.storageDict['index'][index2] = tindex
        self.storageDict['lrc'][index2] = tlrc
        self.storageDict['path'][index2] = tpath
        self.storageDict['time'][index2] = ttime


class Example(QMainWindow):
    resized = QtCore.pyqtSignal()
    def __init__(self):
        super().__init__()
         
        self.initParameters()

        self.initUI()
        self.resized.connect(self.onWindowResized)
    
    def resizeEvent(self, event):
        self.resized.emit()
        return super(Example, self).resizeEvent(event)

    def initParameters(self):
        self.default_save_dir = None
        self.projectName = ""
        self.mvm = MV()
        self.lrcs = []
        self.lrcFileName = None
        self.songFileName = None
        self.lrcSelected = None
        self.storageState = Storage()
        self.maxIndexOfLrcList = 0
        self.previewIng = False
        self.selectedFont = QFont()
        self.selectedColor = QColor()
        self.w = 1024
        self.h = 1024
        self.font_x = 0
        self.font_y = 1023

    def initUI(self):
        # action
        openFile = QAction(QIcon("open.png"), 'Open Lrc', self)
        openFile.setShortcut('Ctrl+O')
        openFile.setStatusTip('Open lrc File')
        openFile.triggered.connect(self.OpenTXTLRCDialog)

        openMusicFile = QAction(QIcon("open.png"), 'Open Music', self)
        openMusicFile.setShortcut('Ctrl+Alt+O')
        openMusicFile.setStatusTip('Open music File')
        openMusicFile.triggered.connect(self.OpenMUSICDialog)

        kickJ = QAction(QIcon("kick.png"), 'Kick', self)
        kickJ.setShortcut('Ctrl+J')
        kickJ.triggered.connect(self.kick)

        save = QAction(QIcon("save.png"), 'Save', self)
        save.setShortcut('Ctrl+S')
        save.triggered.connect(self.save)

        load = QAction(QIcon("load.png"), 'Load', self)
        load.setShortcut('Ctrl+L')
        load.triggered.connect(self.reloadState)
        
        # menubar
        menubar = self.menuBar()
        lrcMenu = menubar.addMenu('&文件与目录')
        lrcMenu.addAction(openFile)

        musicMenu = menubar.addMenu('&音乐')
        musicMenu.addAction(openMusicFile)

        kickMenu = menubar.addMenu('&打点')
        kickMenu.addAction(kickJ)

        saveMenu = menubar.addMenu('&保存')
        saveMenu.addAction(save)

        loadMenu = menubar.addMenu('&加载')
        loadMenu.addAction(load)

        # statusbar
        self.statusBar()

        '''
            |  preview  |
        lrc |           | pick img
            |   edit    |
        '''

        # lrc part
        '''
        insert | remove | up | down 
        buttonStart | buttonAStart | add local
        -----------------------------------
        time | lrc | prompt | buttonStart | 
        '''
        left_layout = QVBoxLayout()
        left_layout.setContentsMargins(10, 10, 0, 0)

        left_top_layout2 = QHBoxLayout()
        left_top_layout2.setContentsMargins(0, 0, 0, 0)
        self.start_button = QPushButton("生成")
        self.start_button.clicked.connect(self.onStartButton)
        self.all_start_button = QPushButton("全部生成")
        self.all_start_button.clicked.connect(self.onAllStartButton)
        self.style_combobox = QComboBox(self)
        self.style_combobox.addItem("油画")
        self.style_combobox.addItem("水彩画")
        self.style_combobox.addItem("卡通")
        self.style_combobox.addItem("粉笔画")
        self.style_combobox.addItem("儿童画")
        self.style_combobox.addItem("蜡笔画")
        self.add_button = QPushButton("添加本地文件")
        self.add_button.clicked.connect(self.onAddLocalFile)
        left_top_layout2.addWidget(self.start_button)
        left_top_layout2.addWidget(self.all_start_button)
        left_top_layout2.addWidget(self.style_combobox)
        left_top_layout2.addWidget(self.add_button)
        left_top_container2 = QWidget()
        left_top_container2.setLayout(left_top_layout2)
        # left_layout.addWidget(QSpacer())
        left_layout.addWidget(left_top_container2)

        self.lrc_list = QListWidget()
        left_layout.addWidget(self.lrc_list)

        action = partial(new_action, self)
        
        # self.GenDialog = GenerateDialog(parent=self)

        self.lrc_menu = QMenu()
        insertUp = action("插入上", self.onInsertButtonUp, 'Ctrl+I', tip="insert up")
        insertDown = action("插入下", self.onInsertButtonDown, 'Ctrl+I', tip="insert down")
        removeLrc = action("删除", self.onRemoveButton, 'Ctrl+R', tip="remove lrc")
        swapUp = action("上移", self.swapUp, tip="swap up")
        swapDown = action("下移", self.swapDown, tip="swap_data")
        add_actions(self.lrc_menu, (insertUp, insertDown, removeLrc, swapUp, swapDown))
        
        self.lrc_list.setContextMenuPolicy(Qt.CustomContextMenu)
        self.lrc_list.customContextMenuRequested.connect(self.popLrcListMenu)
        left_container = QWidget()
        left_container.setLayout(left_layout)
        left_container.setFixedWidth(350)
        self.lrc_list.itemClicked.connect(self.lrcItemClicked)
        self.left_dock = QDockWidget()
        self.left_dock.setObjectName("LRC")
        self.left_dock.setWidget(left_container)

        # edit part

        '''
        auto-resize widget
        '''
        center_layout = QVBoxLayout()
        center_layout.setContentsMargins(5, 10, 5, 0)
        self.imgLabel = QLabel()
        self.imgLabel.setScaledContents(True)
        self.imgLabel.setStyleSheet(
            "QLabel{color: red;background-color: white;border: 1px solid blue;}"
        )

        spacerItem = QSpacerItem(450, 20, QSizePolicy.Fixed, QSizePolicy.Minimum)
        '''
        add lrc? lrc color, lrc position, lrc font?
        effect? zoom in? zomm out?
        '''
        self.playerPlayButton = QPushButton("播放")
        self.playerPlayButton.clicked.connect(self.onPlayerPlayButton)
        self.player_slider = QSlider(Qt.Horizontal)
        self.player_slider.sliderMoved.connect(self.updatePosition)
        self.time_label = QLabel('0:0,000')
        self.time_label.setText("Time")
        slider_layout = QHBoxLayout()
        slider_layout.addWidget(self.playerPlayButton)
        slider_layout.addWidget(self.player_slider)
        slider_layout.addWidget(self.time_label)
        self.slider_container = QWidget()
        self.slider_container.setLayout(slider_layout)

        '''
        x:x font
        y:y color
        '''
        self.postprocessTab = QTabWidget()
        self.postprocessTab.setTabText(0, "字幕")
        self.postprocessTab.setTabText(1, "预览")
        self.postprocessTab.setTabText(2, "导出")
        self.tab1 = QWidget()
        tab1_layout = QGridLayout()
        tab1_layout.setSpacing(3)
        self.useCaptionCheckbox = QCheckBox("添加字幕")
        self.useCaptionCheckbox.setChecked(False)
        self.useCaptionCheckbox.stateChanged.connect(self.onUseCaptionCheckbox)
        labelx = QLabel("x:")
        labely = QLabel("y:")
        labelx.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
        labely.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
        self.inputx = QLineEdit("0")
        self.x_slider = QSlider(Qt.Horizontal)
        self.x_slider.sliderMoved.connect(self.OnxSliderMoved)
        self.x_slider.setRange(0, self.w)
        self.x_slider.setEnabled(True)
        self.inputy = QLineEdit("1023")
        self.inputx.setFixedWidth(50)
        self.inputy.setFixedWidth(50)
        self.inputx.textChanged.connect(self.onXLEtoSlider)
        self.inputy.textChanged.connect(self.onYLEtoSlider)
        self.y_slider = QSlider(Qt.Vertical)
        self.y_slider.sliderMoved.connect(self.OnySliderMoved)
        self.y_slider.setRange(0, self.h)
        self.y_slider.setEnabled(True)
        self.colorButton = QPushButton('选择颜色')
        self.colorButton.clicked.connect(self.onColorButton)
        self.colorFrame = QFrame()
        self.colorFrame.setFixedSize(QSize(50, 22))
        self.fontButton = QPushButton('字体')
        self.fontButton.clicked.connect(self.onFontButton)
        self.inputx.setEnabled(False)
        self.inputy.setEnabled(False)
        self.colorButton.setEnabled(False)
        self.colorFrame.setStyleSheet("QWidget { background-color: black }")
        tab1_layout.addWidget(self.useCaptionCheckbox, 0, 0)
        tab1_layout.addWidget(self.colorButton, 1, 0)
        tab1_layout.addWidget(self.colorFrame, 1, 1)
        tab1_layout.addWidget(self.fontButton, 2, 0)
        tab1_layout.addWidget(labelx, 3, 0)
        tab1_layout.addWidget(self.inputx, 3, 1)
        tab1_layout.addWidget(self.x_slider, 3, 2, 1, 2)

        tab1_layout.addWidget(labely, 1, 2)
        tab1_layout.addWidget(self.inputy, 1, 3)
        tab1_layout.addWidget(self.y_slider, 0, 4, 4, 1)
        
        
        self.tab1.setLayout(tab1_layout)

        self.tab2 = QWidget()
        tab2_layout = QGridLayout()
        preview_button = QPushButton("预览")
        preview_button.clicked.connect(self.onPreview)
        previewSimple_button = QPushButton("简单预览")
        previewSimple_button.clicked.connect(self.onPreviewSimple)
        tab2_layout.addWidget(preview_button)
        tab2_layout.addWidget(previewSimple_button)
        self.tab2.setLayout(tab2_layout)


        self.tab3 = QWidget()
        tab3_layout = QGridLayout()
        export_button = QPushButton("匹配导出")
        export_button.clicked.connect(self.onExportButton)
        exportSimple_button = QPushButton("简单导出")
        exportSimple_button.clicked.connect(self.onExportSimpleButton)
        tab3_layout.addWidget(export_button)
        tab3_layout.addWidget(exportSimple_button)
        self.tab3.setLayout(tab3_layout)

        self.postprocessTab.addTab(self.tab1, "字幕")
        self.postprocessTab.addTab(self.tab2, "预览")
        self.postprocessTab.addTab(self.tab3, "导出")

        self.edit_layout = QVBoxLayout()
        self.edit_layout.addWidget(self.slider_container) #, 0, Qt.AlignCenter)
        self.edit_layout.addWidget(self.postprocessTab)

        self.edit_container = QWidget()
        self.edit_container.setFixedHeight(200)
        self.edit_container.setLayout(self.edit_layout)
        # self.edit_container.setStyleSheet(
        #     "QWidget{color: red;background-color: white;border: 1px solid blue;}"
        # )
        center_layout.addWidget(self.imgLabel)
        center_layout.addItem(spacerItem)
        center_layout.addWidget(self.edit_container)
        self.center_container = QWidget()
        self.center_container.setLayout(center_layout)

        self.player = QMediaPlayer()
        # self.player.setVideoOutput(self.vw)
        self.player.durationChanged.connect(self.getDuration)
        self.player.positionChanged.connect(self.getPosition)
        self.player.setVolume(50)

        # preview part 
        '''
        video widget?
        '''
        right_layout = QVBoxLayout()
        self.image_list = QListWidget()
        right_layout.setContentsMargins(0, 10, 10, 0)
        right_layout.addWidget(self.image_list)
        
        right_container = QWidget()
        right_container.setLayout(right_layout)
        right_container.setFixedWidth(500)
        self.rightDock = QDockWidget()
        self.rightDock.setObjectName("Images")
        self.rightDock.setWidget(right_container)
        # img part
        '''
        ---
        img
        img
        img
        '''
        
        self.setCentralWidget(self.center_container)
        # self.setCentralWidget(self.lrc_list)
        self.addDockWidget(Qt.LeftDockWidgetArea, self.left_dock)
        self.dock_features = QDockWidget.DockWidgetClosable | QDockWidget.DockWidgetFloatable
        # self.left_dock.setFeatures(self.left_dock.features() ^ self.dock_features)
        
        self.left_dock.setTitleBarWidget(QWidget())
        self.left_dock.setFeatures(QDockWidget.NoDockWidgetFeatures)

        self.addDockWidget(Qt.RightDockWidgetArea, self.rightDock)
        # self.rightDock.setFeatures(self.rightDock.features() ^ self.dock_features)
        self.rightDock.setTitleBarWidget(QWidget())
        self.rightDock.setFeatures(QDockWidget.NoDockWidgetFeatures)

        self.setGeometry(0, 0, 1300, 720)
        self.setMinimumSize(QSize(1300,720))
        self.setWindowTitle('MV Maker')
        self.show()

    def OpenTXTLRCDialog(self):
        filters = "Txt & Lrc files (%s)" % ' '.join(['*.txt','*.lrc'])
        filename = QFileDialog.getOpenFileName(self, 'Open file', '.', filters)
        if filename:
            if isinstance(filename, (tuple, list)):
                filename = filename[0]
            self.lrcFileName = filename
            self.StartProject(filename)

    def OpenMUSICDialog(self):
        self.previewIng = False
        filters = "Music files (%s)" % ' '.join(['*flac', '*mp3', '*wav', '*wave', '*dsf', '*dff', '*dsdiff', '*ape', '*m4a'])
        filename = QFileDialog.getOpenFileName(self, 'Open Music file', '.', filters)
        if filename:
            if isinstance(filename, (tuple, list)):
                filename = filename[0]
            self.songFileName = filename
            self.player.setMedia(QMediaContent(QUrl.fromLocalFile(self.songFileName)))

    def StartProject(self, filename):
        self.previewIng = False
        self.lrc_list.clear()
        self.lrcSelected = None
        basename = os.path.basename(filename)
        fn, ext = os.path.splitext(basename)
        self.change_save_dir_dialog()

        if ext == ".txt":
            with open(filename, 'r', encoding='UTF-8') as fp:
                lines = fp.readlines()
                for index, line in enumerate(lines):
                    line = line.replace("\n", "")
                    self.lrcs.append(line)
                    # print(line)
                    widget = self.getLrcItem(line)
                    item = QListWidgetItem()
                    item.setSizeHint(QSize(300, 50))
                    self.lrc_list.addItem(item)
                    self.lrc_list.setItemWidget(item, widget)
                    self.storageState.append(index, line, "", QTime(0,0))
                    
        imglist = glob.glob(os.path.join(self.default_save_dir, "*.png"))
        # print(len(imglist))
        self.image_list.clear()
        # for imgPath in imglist:
        #     print(imgPath)
        #     widget, theight = self.getImgItem(imgPath)
        #     item = QListWidgetItem()
        #     item.setToolTip(imgPath)
        #     item.setSizeHint(QSize(465, theight))
        #     self.image_list.addItem(item)
        #     self.image_list.setItemWidget(item, widget)
            
    def reloadState(self):
        '''
        open the save file
        '''
        saveFileName = os.path.join(self.default_save_dir, 'storage.csv')
        file = open(saveFileName, encoding='utf8')
        loadstorage = pd.read_csv(file, encoding='utf8')

        # loadstorage = pd.read_csv(saveFileName, encoding="gbk")
        self.lrc_list.clear()
        self.storageState.reset()
        for index, row in loadstorage.iterrows():
            # print(type(row))
            # print(row['lrc'])
            # print(row['time'])
            widget = self.getLrcItem(row['lrc'], QTime(0,0) if type(row['time']) != str else QTime.fromString(row['time'], Qt.ISODateWithMs))
            item = QListWidgetItem()
            item.setSizeHint(QSize(300, 50))
            if type(row['path']) == str:
                item.setToolTip(row['path'])
            self.lrc_list.addItem(item)
            self.lrc_list.setItemWidget(item, widget)
            self.storageState.append(row['index'], row['lrc'], "" if type(row['path']) != str else row['path'], QTime(0,0) if type(row['time']) != str else QTime.fromString(row['time'], Qt.ISODateWithMs))       
        self.previewIng = False

    def getLrcItem(self, data, dtime=None):
        # print(dtime)
        widget = QWidget()
        layout_main = QHBoxLayout()
        lrc_time = QTimeEdit()
        lrc_time.setCurrentSection(QDateTimeEdit.MSecSection)
        lrc_time.setDisplayFormat("mm:ss,zzz")
        if dtime is not None:
            lrc_time.setTime(dtime)
        
        lrc_input = QLineEdit(text=data)
        layout_main.addWidget(lrc_time)
        layout_main.addWidget(lrc_input)
        widget.setLayout(layout_main)
        lrc_time.timeChanged.connect(partial(self.onTimeChanged, lrc_time.parent()))
        return widget

    def onAllStartButton(self):
        # 多线程
        # if selected xxxxxx
        item = self.current_item()
        selectedRow = 0
        if not item:
            selectedRow = 0
        else:
            selectedRow = self.lrc_list.row(item)

        textlist = []
        style = self.style_combobox.currentText()
        for i in range(self.lrc_list.count()):
            if i < selectedRow:
                continue
            widget = self.lrc_list.itemWidget(self.lrc_list.item(i))
            obj = widget.findChildren(QLineEdit)
            text = obj[1].text()
            self.status("正在以"+style+"风格画歌词"+text, 5000)
            textlist.append(text)
        
        self.GenDialog = GenerateDialog(self, self.mvm, textlist, style, self.default_save_dir)
        self.GenDialog.popUp()
        
        self.lrc_list.scrollToItem(self.lrc_list.item(0))
        self.lrc_list.setCurrentRow(0)

        widget = self.lrc_list.itemWidget(self.lrc_list.item(0))
        obj = widget.findChildren(QLineEdit)
        text = obj[1].text()

        currentImages = glob.glob(os.path.join(self.default_save_dir, text+"_*.png"))
        
        currentImages.sort(key=lambda item: int(item.split('_')[-1].split(".")[0]))

        self.image_list.clear()

        for imgPath in currentImages:
            widget, newHeight = self.getImgItem(imgPath)
            item = QListWidgetItem()
            item.setSizeHint(QSize(465, newHeight))
            self.image_list.addItem(item)
            self.image_list.setItemWidget(item, widget)

    def onAddLocalFile(self):
        item = self.current_item()
        if not item:
            return
        selectedRow = self.lrc_list.row(item)
        filters = "jpg & png files (%s)" % ' '.join(['*.jpg','*.png'])
        filename = QFileDialog.getOpenFileName(self, 'add local file', '.', filters)
        if filename:
            if isinstance(filename, (tuple, list)):
                filename = filename[0]
            widget = self.lrc_list.itemWidget(self.lrc_list.item(selectedRow))
            obj = widget.findChildren(QLineEdit)
            text = obj[1].text()
            haveSaved = len(glob.glob(os.path.join(self.default_save_dir, text+"_*.png")))
            timage = Image.open(filename)
            timage.save(os.path.join(self.default_save_dir, text+"_" + str(haveSaved) + ".png"))
        
    def onStartButton(self):
        item = self.current_item()
        if not item:
            return
        selectedRow = self.lrc_list.row(item)
        widget = self.lrc_list.itemWidget(self.lrc_list.item(selectedRow))
        obj = widget.findChildren(QLineEdit)
        text = obj[1].text()
        style = self.style_combobox.currentText()
        # print(style)
        self.status("正在以"+style+"风格画歌词"+text, 5000)
        
        # idict = self.mvm.singleText(text, style, self.default_save_dir)
        # self.mvm.readAndSave(idict, text=text, savedPath=self.default_save_dir)
        
        self.GenDialog = GenerateDialog(self, self.mvm, [text], style, self.default_save_dir)
        self.GenDialog.popUp()
        
        currentImages = glob.glob(os.path.join(self.default_save_dir, text+"_*.png"))
        
        currentImages.sort(key=lambda item: int(item.split('_')[-1].split(".")[0]))

        self.image_list.clear()

        for imgPath in currentImages:
            widget, newHeight = self.getImgItem(imgPath)
            item = QListWidgetItem()
            item.setSizeHint(QSize(465, newHeight))
            self.image_list.addItem(item)
            self.image_list.setItemWidget(item, widget)

    def popLrcListMenu(self, pos):
        self.lrc_menu.exec_(self.lrc_list.mapToGlobal(pos))

    def getImgItem(self, data):
        # run_button.clicked.connect(lambda: self.onButtonSStart(lrc_input))
        # run_button.clicked.connect(partial(self.onButtonSStart, lrc_input, style_combobox))
        widget = QWidget()
        layout_main = QVBoxLayout()
        img_label = QLabel()
        tname = data.split("_")[-1].split(".")[0]
        title_checkbox = QCheckBox(tname)
        title_checkbox.stateChanged.connect(partial(self.OnImgSelected, data))
        cvimg = cv2.imdecode(np.fromfile(data, dtype=np.uint8), 1)
        height, width, depth = cvimg.shape
        cvimg = cv2.cvtColor(cvimg, cv2.COLOR_BGR2RGB)
        image = QImage(cvimg.data, width, height, width * depth, QImage.Format_RGB888)

        if image.isNull():
            self.errorMessage(u'Error opening file',
                                u"<p>Make sure <i>%s</i> is a valid image file." % unicodeFilePath)
            self.status("Error reading %s" % data)
            return False
        self.status("Loaded %s" % os.path.basename(data))

        # pixmap = QPixmap(data)
        # pixmap = QPixmap()
        pixmap = QPixmap.fromImage(image)

        img_label.setPixmap(pixmap)
        img_label.setScaledContents(True)
        layout_main.addWidget(img_label)
        layout_main.addWidget(title_checkbox)
        widget.setLayout(layout_main)
        
        return widget, int(455 / width * height)  

    def OnImgSelected(self, data):
        item = self.current_item()
        if not item:
            return
        selectedRow = self.lrc_list.row(item)
        self.storageState.modifyPathByIndex(selectedRow, data)
        item.setToolTip(data)

    def onTimeChanged(self, parent, time):
        self.previewIng = False
        item = self.lrc_list.itemAt(parent.pos())
        if not item:
            return   
        selectedRow = self.lrc_list.row(item)
        self.storageState.modifyTimeByIndex(selectedRow, time)

    def onInsertButtonUp(self):
        item = self.current_item()
        if not item:
            return
        selectedRow = self.lrc_list.row(item)
        item = QListWidgetItem()
        item.setSizeHint(QSize(300, 50))
        self.lrc_list.insertItem(selectedRow, item)
        widget = self.getLrcItem("")
        self.lrc_list.setItemWidget(item, widget)
        self.storageState.insert(selectedRow, self.storageState.maxIndex+1, "", "", QTime(0,0))
        self.previewIng = False

    def onPlayerPlayButton(self):
        if self.playerPlayButton.text() == "播放":
            self.player.play()
            self.playerPlayButton.setText("暂停")
        else:
            self.player.pause()
            self.playerPlayButton.setText("播放")

    def onInsertButtonDown(self):
        item = self.current_item()
        if not item:
            return
        selectedRow = self.lrc_list.row(item)
        item = QListWidgetItem()
        item.setSizeHint(QSize(300, 50))
        self.lrc_list.insertItem(selectedRow+1, item)
        widget = self.getLrcItem("")
        self.lrc_list.setItemWidget(item, widget)
        self.storageState.insert(selectedRow+1, self.storageState.maxIndex+1, "", "", QTime(0,0))
        self.previewIng = False

    def onRemoveButton(self):
        item = self.current_item()
        if not item:
            return
        selectedRow = self.lrc_list.row(item)
        self.lrc_list.takeItem(selectedRow)
        self.storageState.delete(selectedRow)
        self.previewIng = False

    def swapUp(self):
        item = self.current_item()
        if not item:
            return
        selectedRow = self.lrc_list.row(item)
        if selectedRow > 0:
            widgetc = self.lrc_list.itemWidget(item)
            widgett = self.lrc_list.itemWidget(self.lrc_list.item(selectedRow - 1))
            textwidgetc = widgetc.findChildren(QLineEdit)
            textwidgett = widgett.findChildren(QLineEdit)
            textc = textwidgetc[1].text()
            textt = textwidgett[1].text()
            textwidgett[1].setText(textc)
            textwidgetc[1].setText(textt)
            self.storageState.swapTwoByIndex(selectedRow, selectedRow-1)
        self.previewIng = False

    def swapDown(self):
        item = self.current_item()
        if not item:
            return
        selectedRow = self.lrc_list.row(item)
        if selectedRow < self.lrc_list.count() - 1:
            widgetc = self.lrc_list.itemWidget(item)
            widgett = self.lrc_list.itemWidget(self.lrc_list.item(selectedRow + 1))
            textwidgetc = widgetc.findChildren(QLineEdit)
            textwidgett = widgett.findChildren(QLineEdit)
            textc = textwidgetc[1].text()
            textt = textwidgett[1].text()
            textwidgett[1].setText(textc)
            textwidgetc[1].setText(textt)
            self.storageState.swapTwoByIndex(selectedRow, selectedRow+1)
        self.previewIng = False

    def onColorButton(self):
        col = QColorDialog.getColor()
        if col.isValid():
            self.colorFrame.setStyleSheet("QWidget { background-color: %s }"
                % col.name())
            self.selectedColor = col
        else:
            self.selectedColor = QColor()
            self.colorFrame.setStyleSheet("QWidget { background-color: %s }"
                % self.selectedColor)

    def onFontButton(self):
        font, ok = QFontDialog.getFont()
        if ok:
            self.selectedFont = font

    def onPreview(self, export=False):
        if not self.checkState():
            # print("check failure")
            return False
        self.previewIng = True
        
        self.timePreview = []
        for itemIndex in range(self.lrc_list.count()):
            item = self.lrc_list.item(itemIndex)
            ctime = self.lrc_list.itemWidget(item).findChildren(QTimeEdit)[0].time().msecsSinceStartOfDay()
            self.timePreview.append(ctime)
        self.timePreview.append(self.videoLength)
        if not export: 
            self.playerPlayButton.setText("暂停")
            self.player.play()
          
    def onPreviewSimple(self):
        pass

    def onExportButton(self):
        if not self.checkState():
            return False
        self.onPreview(export=True)
        
        fourcc = cv2.VideoWriter_fourcc(*'mp4v')
        fps = 25
        outfilename = os.path.join(self.default_save_dir, ".tmp.mp4")
        outter = cv2.VideoWriter(outfilename, fourcc, fps, (self.w, self.h))
        
        self.exportdialog = ExportDialog(self, outter, outfilename)
        self.exportdialog.popUp()

    def onExportSimpleButton(self):
        fourcc = cv2.VideoWriter_fourcc(*'mp4v')
        fps = 25
        outfilename = os.path.join(self.default_save_dir, ".tmp.mp4")
        outter = cv2.VideoWriter(outfilename, fourcc, fps, (self.w, self.h))
        
        imglist = glob.glob(os.path.join(self.default_save_dir, "*.png"))
        pindex = -1
        i = 0
        cimage = None
        maxframe = (self.parent.videoLength // 40 + 1) * 40
        while i < maxframe:
            index = self.parent.getIndex(i)
            if index == pindex:
                pass
            else:
                if index < self.parent.lrc_list.count():
                    imgpath = self.parent.lrc_list.item(index).toolTip()
                    text = self.parent.lrc_list.itemWidget(self.parent.lrc_list.item(index)).findChildren(QLineEdit)[1].text()
                    cimage = self.parent.imageShowOnLabel(imgpath, lrc=text, back=True)
                    self.listValue.emit(text)
                pindex = index
            i += 40
            self.outter.write(cimage)
            self.progressBarValue.emit(i * 1.0 / maxframe * 50)
        self.outter.release()
    
    def onWindowResized(self):
        # print(self.width(), self.height())
        newWidth = self.width() - 500 - 350
        newHeight = self.height() - 200
        tsize = QSize(newWidth, newHeight)
        self.imgLabel.resize(tsize)
        qpixmap = self.imgLabel.pixmap()
        if qpixmap is not None:
            #qpixmap = qpixmap.scaled(tsize, aspectRatioMode=Qt.KeepAspectRatio)
            self.imgLabel.setPixmap(qpixmap)
            # print("some function")

    def onUseCaptionCheckbox(self):
        if self.useCaptionCheckbox.isChecked():
            self.inputx.setEnabled(True)
            self.inputy.setEnabled(True)
            self.x_slider.setEnabled(True)
            self.y_slider.setEnabled(True)
            self.colorButton.setEnabled(True)
            self.fontButton.setEnabled(True)
            if not self.previewIng:
                item = self.current_item()
                if item:
                    text = self.lrc_list.itemWidget(item).findChildren(QLineEdit)[1].text()
                    self.imageShowOnLabel("", lrc=text, cbByFC=True)
        else:
            self.inputx.setEnabled(False)
            self.inputy.setEnabled(False)
            self.x_slider.setEnabled(False)
            self.y_slider.setEnabled(False)
            self.colorButton.setEnabled(False)
            self.fontButton.setEnabled(False)

    def current_item(self):
        items = self.lrc_list.selectedItems()
        if items:
            return items[0]
        return None

    def change_save_dir_dialog(self, _value=False):
        if self.default_save_dir is not None:
            path = ustr(self.default_save_dir)
        else:
            path = '.'

        dir_path = ustr(QFileDialog.getExistingDirectory(self,
                                                         '%s - Save project to the directory' % "Create Project", path,  QFileDialog.ShowDirsOnly
                                                         | QFileDialog.DontResolveSymlinks))
        # print(dir_path)
        if dir_path is not None and len(dir_path) > 1:
            self.default_save_dir = dir_path

        '''
        open a csv file to store state
        '''

        self.status('%s . Project will be saved to %s' % ('Change saved folder', self.default_save_dir))

    def updatePosition(self, v):
        self.player.setPosition(v)
        self.displayTime(self.player_slider.maximum() - v)

    def getDuration(self, d):
        self.videoLength = d
        self.player_slider.setRange(0, d)
        self.player_slider.setEnabled(True)
        self.displayTime(d)

    def getIndex(self, p):
        for index, i in enumerate(self.timePreview):
            if p < i:
                return index
        return len(self.timePreview)

    def drawCaption(self, qpm, text):
        print(text)
        qp = QPainter(qpm)
        qp.begin(self)
        pen = QPen(self.selectedColor)
        pen.setWidth(2)
        qp.setPen(pen)        
        if self.selectedFont is None:
            font = QFont()
            font.setFamily('Times')
            font.setBold(True)
            font.setPointSize(24)
        else:
            font = self.selectedFont
        qp.setFont(font)
        qp.drawText(self.font_x, self.font_y, text)
        qp.end()
        return qpm

    def OnxSliderMoved(self, value):
        self.inputx.setText(str(value))
        self.font_x = value

    def OnySliderMoved(self, value):
        self.inputy.setText(str(self.h - value))
        self.font_y = self.h - value

    def onXLEtoSlider(self, value):
        if value == "":
            return
        try:
            v = int(value)
        except Exception as e:
            print("except:", e)
        else:
            v = max(0, min(v, self.w - 1))
            self.inputx.setText(str(v))
            self.x_slider.setValue(v)       

    def onYLEtoSlider(self, value):
        if value == "":
            return
        try:
            v = int(value)
        except Exception as e:
            print("except:", e)
        else:
            v = max(0, min(v, self.h - 1))
            self.inputy.setText(str(v))
            self.y_slider.setValue(self.h - v)

    def getPosition(self, p):
        # print("player to slider", p)
        self.player_slider.setValue(p)
        self.displayTime(self.player_slider.maximum() - p)
        if self.previewIng:
            index = self.getIndex(p)
            # print(index, self.lrc_list.count())
            if index < self.lrc_list.count():
                # print("------")
                # print(self.lrc_list.item(index).toolTip())
                # print(self.lrc_list.itemWidget(self.lrc_list.item(index)).findChildren(QLineEdit)[1].text())
                
                # get the picked img
                imgpath = self.lrc_list.item(index).toolTip()
                text = self.lrc_list.itemWidget(self.lrc_list.item(index)).findChildren(QLineEdit)[1].text()
                self.imageShowOnLabel(imgpath, lrc=text)
            

    def kick(self):
        if self.lrcSelected is None:
            return
        # self.player.pause()
        timestamp = self.player.position()
        # print(timestamp)
        widget = self.lrc_list.itemWidget(self.lrc_list.item(self.lrcSelected))
        h = math.floor(timestamp / 3600000)
        m = math.floor(max(timestamp - h * 3600000, 0) / 60000)
        s = math.floor(max(timestamp - h * 3600000 - m * 60000, 0) / 1000) 
        z = timestamp % 1000
        obj = widget.findChildren(QTimeEdit)
        obj[0].setTime(QTime(h,m,s,z))
        self.lrcSelected += 1
        self.lrc_list.scrollToItem(self.lrc_list.item(self.lrcSelected))
        self.lrc_list.setCurrentRow(self.lrcSelected)

    def displayTime(self, ms):
        h = math.floor(ms / 3600000)
        m = math.floor(max(ms - h * 3600000, 0) / 60000)
        s = math.floor(max(ms - h * 3600000 - m * 60000, 0) / 1000) 
        z = ms % 1000
        self.time_label.setText('{}:{}:{},{}'.format(h,m,s,z))

    def imageShowOnLabel(self, imgpath, lrc=None, back=False, cbByFC=False):
        print(lrc)
        qpixmap = None
        if cbByFC:
            qpixmap = self.imgLabel.pixmap()
            if qpixmap is None:
                print("return?")
                return
        else:
            if imgpath is "":
                qpixmap = QPixmap("resources/defaultImg.png")
            else:
                qpixmap = QPixmap(imgpath)
        # if caption
        if self.useCaptionCheckbox.isChecked():
            print("true")
            if lrc:
                print("true")
                qpixmap = self.drawCaption(qpixmap, lrc)
        # put it on the canvas
        if back:            
            return cv2.cvtColor(np.array(ImageQt.fromqpixmap(qpixmap)), cv2.COLOR_RGB2BGR) 
        else:
            # tsize = self.imgLabel.size()
            # qpixmap = qpixmap.scaled(tsize, aspectRatioMode=Qt.KeepAspectRatio)
            if cbByFC:
                self.imgLabel.setPixmap(qpixmap)
            else:
                self.imgLabel.setPixmap(qpixmap)

    def lrcItemClicked(self, item):
        self.lrcSelected = self.lrc_list.row(item)
        text = self.lrc_list.itemWidget(item).findChildren(QLineEdit)[1].text()
        # print(text)
        currentImages = glob.glob(os.path.join(self.default_save_dir, text+"_*.png"))
        currentImages.sort(key=lambda item: int(item.split('_')[-1].split(".")[0]))

        if item.toolTip() != "":
            imgPath = item.toolTip()
            self.imageShowOnLabel(imgPath, lrc=text) 
        else:
            self.imageShowOnLabel("") 

        self.image_list.clear()
        for imgPath in currentImages:
            widget, newHeight = self.getImgItem(imgPath)
            item = QListWidgetItem()
            item.setSizeHint(QSize(465, newHeight))
            self.image_list.addItem(item)
            self.image_list.setItemWidget(item, widget)  

    def checkpre(self):
        if self.lrc_list.count() > 0 and self.default_save_dir is not None and self.songFileName is not None:
            return True
        else:
            return False

    def checkState(self):
        if not self.checkpre():
            reply = QMessageBox.warning(self, '前置检测', '没有导入歌词或音频文件', QMessageBox.Yes, QMessageBox.Yes) 
            # print("failure in checkpre")
            if reply == QMessageBox.Yes:
                return False
        flag = True
        end = self.lrc_list.count()
        iterTime = QTime(0, 0)
        for i in range(end):
            widget = self.lrc_list.itemWidget(self.lrc_list.item(i))
            obj = widget.findChildren(QTimeEdit)
            currentTime = obj[0].time()
            # print(i)
            # print(currentTime.toString(Qt.ISODateWithMs))
            # print(iterTime.toString(Qt.ISODateWithMs))
            if currentTime.__lt__(iterTime):
                flag = False
                break
            iterTime = currentTime
        if not flag:
            reply = QMessageBox.warning(self, '前置检测', '歌词没有按照时间序', QMessageBox.Yes, QMessageBox.Yes) 
            # print("failure in checkpre")
            if reply == QMessageBox.Yes:
                return flag
        return flag

    def save(self):
        constorage = list(zip(self.storageState.storageDict['index'], 
                                   self.storageState.storageDict['lrc'],
                                   self.storageState.storageDict['path'],
                                   self.storageState.storageDict['time']))
        dfStorage = pd.DataFrame(data=constorage,
                      columns=['index', 'lrc', 'path', 'time'])
        storagePath = os.path.join(self.default_save_dir, "storage.csv")
        dfStorage.to_csv(storagePath, index=False)
        self.status("保存成功", delay=5000)
        # print("save complete!")


    def status(self, message, delay=5000):
        self.statusBar().showMessage(message, delay)
 

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())